local redis = require "resty.redis"
local red = redis:new()
local resty_lock = require "resty.lock"
local ngx_cache = ngx.shared.ngx_cache

local redis_pool = {}

function redis_pool:connect(config)
    red:set_timeout(1000)
    local ok, err = red:connect(config.host, config.port)
    if not ok then
            ngx.say("failed to connect: ", err)
            return
    end
    
    if config.pass ~= '' then
        local res, err = red:auth(config.pass)
        if not res then
            ngx.say("failed to authenticate: ", err)
            return
        end
    end

    red:select(config.database)
end

-- 关闭连接
function redis_pool:close()
    local ok, err = red:close()
    if not ok then
        ngx.say("failed to close: ", err)
        return
    end
end

function set_to_cache(key, value, exptime)
        if not exptime then
                exptime = 0
        end
        local succ, err, forcible = ngx_cache:set(key, value, exptime)
        return succ
end

function redis_pool:get(key)
        local ngx_cache = ngx.shared.ngx_cache;
        local value = ngx_cache:get(key)
        if not value then       -- cache miss
                local lock = resty_lock:new("cache_lock")
                local elapsed, err = lock:lock(key)
                if not elapsed then
                        return fail("failed to acquire the lock: ", err)
                end

                value = redis_pool:getKeyVue(key)
                if not value then
                        local ok, err = lock:unlock()
                        if not ok then
                                return fail("failed to unlock: ", err)
                        end
                        ngx.say("no value found")
                        return
                end

                local ok, err = ngx_cache:set(key, value, 1)
                if not ok then
                        local ok, err = lock:unlock()
                        if not ok then
                                return fail("failed to unlock: ", err)
                        end
                        return faile("failed to update ngx_cache: ", err)
                end

                local ok, err = lock:unlock()
                if not ok then
                        return faile("failed to unlock: ", err)
                end

                return value
        end

        ngx.say("get from cache.")
        return value
end

function redis_pool:getKeyVue(key)
    red:set_timeout(1000)
    local res, err = red:get(key)
    if not res then
            ngx.say("failed to get doy: ", err)
            return ngx.null
    end
    return res
end

function redis_pool:set(key, value)
        red:set_timeout(1000)
        local ok, err = red:set(key, value)
        if not ok then
                ngx.say("failed to set to redis: ", err)
                return
        end
        return ok
end

return redis_pool
